package com.jeeplus.modules.graph.service;

import com.alibaba.fastjson.JSON;
import com.jeeplus.common.utils.StringUtils;
import com.jeeplus.core.service.CrudService;
import com.jeeplus.modules.graph.entity.ByReason;
import com.jeeplus.modules.graph.entity.Choice;
import com.jeeplus.modules.graph.entity.Evaluation;
import com.jeeplus.modules.graph.entity.GraphPairDataUI;
import com.jeeplus.modules.graph.mapper.GraphMapper;
import com.jeeplus.modules.studentevaluate.entity.StudentEvaluate;
import com.jeeplus.modules.sys.entity.StudentMoreduMain;
import com.jeeplus.modules.sys.entity.StudentMoreduViceAdd;
import com.jeeplus.modules.sys.entity.StudentMoreduViceSub;
import com.jeeplus.modules.sys.mapper.StudentMoreduMainMapper;
import com.jeeplus.modules.sys.mapper.StudentMoreduViceAddMapper;
import com.jeeplus.modules.sys.mapper.StudentMoreduViceSubMapper;
import io.lettuce.core.StrAlgoArgs;
import liquibase.pro.packaged.A;
import liquibase.pro.packaged.B;
import liquibase.pro.packaged.E;
import liquibase.pro.packaged.S;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

/**
 * 图表Service
 * Created by 于昭龙 on 2022/5/4.
 */
@Service
@Transactional(readOnly = true)
public class GraphService extends CrudService<StudentMoreduMainMapper, StudentMoreduMain> {
    @Autowired
    StudentMoreduViceAddMapper studentMoreduViceAddMapper;
    @Autowired
    StudentMoreduViceSubMapper studentMoreduViceSubMapper;
    @Autowired
    GraphMapper graphMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    /**
     * 取到按学生分类的所有学生的加减分数据
     * 按条件取得
     * @return
     */
    public List<StudentMoreduMain> getstudentGraph(StudentMoreduMain studentMoreduMain) {
        List<StudentMoreduMain> list = graphMapper.findList(studentMoreduMain);
        for (StudentMoreduMain student :list) {
            StudentMoreduViceAdd ta = new StudentMoreduViceAdd();
            ta.setAddId(student.getId());
            student.setStudentMoreduViceAddList(studentMoreduViceAddMapper.findAllList(ta));
            StudentMoreduViceSub ts = new StudentMoreduViceSub();
            ts.setSubId(student.getId());
            student.setStudentMoreduViceSubList(studentMoreduViceSubMapper.findAllList(ts));
        }
        return list;
    }

    /**
     * 联合接口
     * 一级、二级、三级的总分、平均分
     * 校级、系级、年级的总分、平均分
     * @param studentMoreduMain 学院 年级 班级
     * @param ids 学院的父亲路径
     * @param flag 选择是统计还是百分比
     */
    public Map<String,Double> getPointOrEveragePoint(StudentMoreduMain studentMoreduMain, String ids,String flag){
        //这是根据条件获得的全部的学生
        List<StudentMoreduMain> studentGraph = this.getstudentGraph(studentMoreduMain);
        //这是通过路径获得的对应的下级office
        List<String> offices = graphMapper.getOffices(ids);
        //检查这是几级
        int val = 0;
        for (int i = 0; i < ids.length(); i++) {
            if ((int)ids.charAt(i) == 44){
               val++;
            }
        }
        //转成map
        Map<String,Double> allpoint = new HashMap<String,Double>();
        for (String str: offices) {
            allpoint.put(str,0.0);
        }
        //统计 加过滤,年级班级的过滤,或者异常捕获，或者检查锁
        switch (val){
            case 2://系级
                for (StudentMoreduMain stu :studentGraph){
                    try {
                        allpoint.put(stu.getInstitute(),allpoint.get(stu.getInstitute())+stu.getCurrentMoraleduPoint());
                    }catch(Exception e){
                        System.out.println(stu.toString());
                    }
                }
                break;
            case 3://年级 系级对劲
                for (StudentMoreduMain stu :studentGraph){
                        allpoint.put(stu.getGrade(),allpoint.get(stu.getGrade())+stu.getCurrentMoraleduPoint());
                }
                break;
            case 4://班级
                for (StudentMoreduMain stu :studentGraph){
                    allpoint.put(stu.getClasse(),allpoint.get(stu.getClasse())+stu.getCurrentMoraleduPoint());
                }
                break;
            default://别的
                throw new RuntimeException("未知等级");
        }
        //处理
        if ("average".equals(flag)){//平均
            // 平均后的全部对应数据
            Map<String,Double> mapeverage = new HashMap<String,Double>();
            // 全部的对应数据
            Set<Entry<String, Double>> allpointentryset = allpoint.entrySet();
            switch (val){
                case 2://系级
                    //要取到系里有多少个年级
                    Double cou2 = (double)graphMapper.getCountYearFromInstitute(ids);
                    for(Entry<String, Double> entry: allpointentryset){
                        if (cou2 != 0) {
                            mapeverage.put(entry.getKey(), entry.getValue() / cou2);
                        } else {
                            mapeverage.put(entry.getKey(), 0.0);
                        }
                    }
                    break;
                case 3://年级
                    //要取到年级有多少班级
                    Double cou3 = (double)graphMapper.getCountClassFromYear(ids);
                    for(Entry<String, Double> entry: allpointentryset){
                        if (cou3 != 0) {
                            mapeverage.put(entry.getKey(), entry.getValue() / cou3);
                        } else {
                            mapeverage.put(entry.getKey(), 0.0);
                        }
                    }
                    break;
                default://别的
                    throw new RuntimeException("未知");
            }
            return mapeverage;
        }
        //求和已经在上一步完成了
        return allpoint;
    }

    /**
     * 根据机构查询成绩单,经过改造可求平均分
     * @param studentMoreduMain  主要参数就三个 学院 年级 班级
     * @return 成绩单
     */
    public List<StudentMoreduMain> getStudentsFromOffice(StudentMoreduMain studentMoreduMain){
        String queryName = this.getClass().getSimpleName()+".getStudentsFromOffice"+ studentMoreduMain.toString();
        // 先去查询缓存
        String reasonListJsonStr = redisTemplate.opsForValue().get(queryName);
        List<StudentMoreduMain> data;
        // 如果缓存中有则直接返回
        if(StringUtils.isNoneBlank(reasonListJsonStr)){
            data = JSON.parseArray(reasonListJsonStr,StudentMoreduMain.class);
            logger.info("走了byReason缓存");
        }else {
            // 缓存中没有则从数据库中查询
            data = graphMapper.getStudentsFromOffice(studentMoreduMain);
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set(queryName, JSON.toJSONString(data), 2, TimeUnit.DAYS);
//            logger.info("放入byReason缓存");
        }
        return data;
    }

//    /**
//     * 查询评价情况
//     * @param evaluation
//     * @return
//     */
//    public List<Evaluation> isEvaluate(String ids,Evaluation evaluation){
//        String temp1 = ids;
//        String temp2 = evaluation.toString();
//        // 查询缓存
//        String evaluateListJsonStr = redisTemplate.opsForValue().get("GraphService.isEvaluate"+temp1+temp2);
//        // 如果缓存中有则直接返回
//        if(StringUtils.isNoneBlank(evaluateListJsonStr)){
//            List<Evaluation> list = JSON.parseArray(evaluateListJsonStr,Evaluation.class);
//            logger.info("走了isEvaluate缓存！");
//            return list;
//        }else {
//            //如果缓存中没有则从数据库中查询
//            //这是根据条件获得的全部的学生
//            List<Evaluation> evaluationList = graphMapper.isEvaluate(evaluation);
//            //这是通过路径获得的对应的下级office
//            List<String> offices = graphMapper.getOffices(ids);
//            //检查这是几级
//            int val = 0;
//            for (int i = 0; i < ids.length(); i++) {
//                if ((int)ids.charAt(i) == 44){
//                    val++;
//                }
//            }
//            //转成map
//            Map<String,Double> allpoint = new HashMap<String,Double>();
//            for (String str: offices) {
//                allpoint.put(str,0.0);
//            }
//            //统计 加过滤,年级班级的过滤,或者异常捕获，或者检查锁
//            switch (val){
//                case 2://系级
//                    for (Evaluation stu :evaluationList){
//                        try {
//                            allpoint.put(stu.getInstitute(),allpoint.get(stu.getInstitute()));
//                        }catch(Exception e){
//                            System.out.println(stu.toString());
//                        }
//                    }
//                    break;
//                case 3://年级 系级对劲
//                    for (Evaluation stu :evaluationList){
//                        allpoint.put(stu.getGrade(),allpoint.get(stu.getGrade()));
//                    }
//                    break;
//                case 4://班级
//                    for (Evaluation stu :evaluationList){
//                        allpoint.put(stu.getClasse(),allpoint.get(stu.getClasse()));
//                    }
//                    break;
//                default://别的
//                    throw new RuntimeException("未知等级");
//            }
//            // 处理
//
//            // 转换成Integer
//            Integer isEval = 0, noEval = 0;
//            for (Evaluation temp : evaluationList){
//                isEval = Integer.parseInt(temp.getIsEvaluate());
//                noEval = Integer.parseInt(temp.getNoEvaluate());
//            }
//
//            // 找一个数据进行存储
//            Evaluation isEvals = new Evaluation(isEval,"已评价");
//            Evaluation noEvals = new Evaluation(noEval,"未评价");
//
//            List<Evaluation> list = Arrays.asList(isEvals,noEvals);
//
//            // 处理数据
//            calculatePercent(list);
//            list = graphMapper.isEvaluate(evaluation);
//
//            // 放入缓存中，120s失效
//            redisTemplate.opsForValue().set("GraphService.isEvaluate"+temp1+temp2,JSON.toJSONString(list),120,TimeUnit.SECONDS);
//            logger.info("放入isEvaluate缓存！");
//            // 返回数据
//            return list;
//        }
//    }

    // 数据处理 相加等于100
//    public static void calculatePercent(List<Evaluation> list) {
//        //求和：所有评价情况
//        int sum = list.stream().mapToInt(Evaluation::getNumber).sum();
//        for (Evaluation evaluation : list) {
//            double value = evaluation.getNumber() * 100 / (double) sum;
//            int valueInt = (int) value;
//            //设置对应的百分比
//            evaluation.setPercent(valueInt);
//            //获取小数点后的值
//            evaluation.setPoint(value - valueInt);
//        }
//        //求和：当前评价情况百分比合计。由于我们舍弃了小数位，所以该合计只会小于等于100
//        int curSum = list.stream().mapToInt(Evaluation::getPercent).sum();
//        while (curSum < 100) {
//            //找出小数余额最大的组，对其进行加1
//            Evaluation max = list.stream().max(Comparator.comparingDouble(Evaluation::getPoint)).get();
//            max.setPercent(max.getPercent() + 1);
//            //当前这个数已经加1了，不应该参与下一轮的竞选
//            max.setPoint(0.0);
//            curSum++;
//        }
//    }

    // 按学院、不分年级的评价情况
    public List<Evaluation> organizatioEvaluationSituation(Evaluation evaluation){
        List<Evaluation> data = graphMapper.organizatioEvaluationSituation(evaluation);
        return data;
    }

    // 按学院、年级分组的评价情况
    public List<Evaluation> evaluationSituation(Evaluation evaluation){
        List<Evaluation> data = graphMapper.evaluationSituation(evaluation);
        return data;
    }

    // 所有学院的评价情况
    public List<Evaluation> allEvaluationSituation(Evaluation evaluation){
        List<Evaluation> data = graphMapper.allEvaluationSituation(evaluation);
        return data;
    }

    public List<ByReason> byReason(StudentMoreduMain studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        // 先去查询缓存
        String reasonListJsonStr = redisTemplate.opsForValue().get("GraphService.byReason"+temp);
        // 如果缓存中有则直接返回
        if(StringUtils.isNoneBlank(reasonListJsonStr)){
            List<ByReason> data = JSON.parseArray(reasonListJsonStr,ByReason.class);
            System.out.println("我有数据ByReason");
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            List<ByReason> data = graphMapper.byReason(studentMoreduMain);
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set("GraphService.byReason"+temp,JSON.toJSONString(data),2, TimeUnit.DAYS);
//            logger.info("放入byReason缓存");
            return data;
        }
    }
    // 原因总分对比图
    public List<ByReason> byReasonContrast(StudentMoreduMain studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        // 先去查询缓存
        String reasonListJsonStr = redisTemplate.opsForValue().get("GraphService.byReason"+temp);
        // 如果缓存中有则直接返回
        if(StringUtils.isNoneBlank(reasonListJsonStr)){
            List<ByReason> data = JSON.parseArray(reasonListJsonStr,ByReason.class);
            logger.info("走了byReason缓存");
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            List<ByReason> data = graphMapper.byReasonContrast(studentMoreduMain);
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set("GraphService.byReason"+temp,JSON.toJSONString(data),2, TimeUnit.DAYS);
//            logger.info("放入byReason缓存");
            return data;
        }
    }

    // 原因平均分对比图
    public List<ByReason> byReasonContrastAve(StudentMoreduMain studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        // 先去查询缓存
        String reasonListJsonStr = redisTemplate.opsForValue().get("GraphService.byReason"+temp);
        // 如果缓存中有则直接返回
        if(StringUtils.isNoneBlank(reasonListJsonStr)){
            List<ByReason> data = JSON.parseArray(reasonListJsonStr,ByReason.class);
            logger.info("走了byReason缓存");
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            List<ByReason> data = graphMapper.byReasonContrastAve(studentMoreduMain);
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set("GraphService.byReason"+temp,JSON.toJSONString(data),2, TimeUnit.DAYS);
//            logger.info("放入byReason缓存");
            return data;
        }
    }

    public List<ByReason> byInstitute(ByReason studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        System.out.println(temp);
        // 先从缓存中查找
        String instituteListJsonStr = redisTemplate.opsForValue().get("GraphService.byInstitute"+temp);
        // 如果有则直接返回
        if(StringUtils.isNoneBlank(instituteListJsonStr)){
            List<ByReason> data = JSON.parseArray(instituteListJsonStr,ByReason.class);
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            //如果年级不为空，那么就按照班级进行分类
            List<ByReason> data;
            if (studentMoreduMain.getGrade() != null && studentMoreduMain.getGrade() != ""){
                data = graphMapper.byInstituteC(studentMoreduMain);
            } else if (studentMoreduMain.getInstitute() != null && studentMoreduMain.getInstitute() != ""){
                //如果学院不为空，那么就按照年级进行分类
                data = graphMapper.byInstituteG(studentMoreduMain);
            } else {
                //如果都是空，那么就按照学院进行分类
                data = graphMapper.byInstituteI(studentMoreduMain);
            }
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set("GraphService.byInstitute"+temp,JSON.toJSONString(data),2,TimeUnit.DAYS);
//            logger.info("放入byInstitute缓存");
            return data;
        }
    }
    public List<GraphPairDataUI> regional(StudentEvaluate studentEvaluate){
        return graphMapper.regional(studentEvaluate);
    }

    // 学院总分对比图
    public List<ByReason> byInstituteContrast(ByReason studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        System.out.println(temp);
        // 先从缓存中查找
        String instituteListJsonStr = redisTemplate.opsForValue().get("GraphService.byInstitute"+temp);
        // 如果有则直接返回
        if(StringUtils.isNoneBlank(instituteListJsonStr)){
            List<ByReason> data = JSON.parseArray(instituteListJsonStr,ByReason.class);
            logger.info("走了byInstitute缓存");
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            //如果年级不为空，那么就按照班级进行分类
            List<ByReason> data;
            data = graphMapper.byInstituteContrast(studentMoreduMain);
            // 放入缓存中，120s失效
            redisTemplate.opsForValue().set("GraphService.byInstitute"+temp,JSON.toJSONString(data),2,TimeUnit.DAYS);
//            logger.info("放入byInstitute缓存");
            return data;
        }
    }
    // 学院平均分对比图
    public List<ByReason> byInstituteContrastAve(ByReason studentMoreduMain) {
        String temp = studentMoreduMain.toString();
        System.out.println(temp);
        // 先从缓存中查找
        String instituteListJsonStr = redisTemplate.opsForValue().get("GraphService.byInstitute"+temp);
        // 如果有则直接返回
        if(StringUtils.isNoneBlank(instituteListJsonStr)){
            List<ByReason> data = JSON.parseArray(instituteListJsonStr,ByReason.class);
            logger.info("走了byInstitute缓存");
            return data;
        }else {
            // 缓存中没有则从数据库中查询
            //如果年级不为空，那么就按照班级进行分类
            List<ByReason> data;
            data = graphMapper.byInstituteContrastAve(studentMoreduMain);
            // 放入缓存中，120s失效
           redisTemplate.opsForValue().set("GraphService.byInstitute"+temp,JSON.toJSONString(data),2,TimeUnit.DAYS);
//            logger.info("放入byInstitute缓存");
            return data;
        }
    }

    // 按学院、不分年级的评价情况
    public List<Choice> getGrade(){
        List<Choice> data = graphMapper.getGrade();
        return data;
    }

    public List<List<Integer>> queryRange(StudentMoreduMain studentMoreduMain) {
        List<List<Integer>> data = new LinkedList<>();
        // 分数
        List<Integer> point = graphMapper.queryRange(studentMoreduMain);
        // 获取最大值和最小值
        Map<String, Double> map = graphMapper.queryRangeMax(studentMoreduMain);
        // 获取区间范围
        Integer range = studentMoreduMain.getCurrentMoraleduPoint();

//        studentMoreduMain.getCurrentMoraleduPoint();  设这个为查询区间范围
        // 初始化
        for (int i = 0; i < Integer.MAX_VALUE; i++){
            List<Integer> temp = new LinkedList<>();
            temp.add(0, i * range);
            // 尾坐标
            temp.add(1,(i+1)* range);
            // 个数
            temp.add(2,0);

            data.add(i,temp);
            if (i * range > map.get("maxPoint")) {
                break;
            }
        }
        System.out.println("=====");
        System.out.println("=====");
        for (Integer tempPoint : point) {
            int index = tempPoint/range;
            List<Integer> LI = data.get(index);
            List<Integer> temp2 = new LinkedList<>();
            temp2.add(0,LI.get(0));
            temp2.add(1,LI.get(1));
            temp2.add(2,LI.get(2)+1);
            // 覆盖原本数据
            data.remove(index);
            data.add(index,temp2);
        }
        return data;
    }

}

